package com.huike.report.services.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huike.clues.domain.TbClue;
import com.huike.clues.domain.vo.ClueReportVo;
import com.huike.clues.mapper.SysDeptMapper;
import com.huike.common.constant.Constants;
import com.huike.common.core.domain.MPentity.*;
import com.huike.common.exception.CustomException;
import com.huike.contract.domain.TbContract;
import com.huike.report.domain.DTO.ContractpageDTO;
import com.huike.report.domain.DTO.TbActivityDTO;
import com.huike.report.domain.DTO.TbCluePageDTO;
import com.huike.report.domain.vo.*;
import com.huike.report.mapper.*;
import com.huike.report.services.SysReportservices;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.*;


/**
 * @Description 统计分析相关接口
 * @Author 小不夜侯
 * @Date 2023-08-29 9:11
 */
@Service
public class SysReportservicesImpl extends ServiceImpl<SysReportMapper,Contract> implements SysReportservices {
    @Resource
    private SysReportMapper sysReportMapper;

    /**
     * 客户统计明细列表
     *
     * @param contractpageDTO
     * @return
     */


    @Override
    public List<TbContract> selectpage1(ContractpageDTO contractpageDTO) {
        return sysReportMapper.selectPageContract(contractpageDTO);
    }

    /**
     * 统计新增客户
     *
     * @param beginCreate
     * @param endCreate
     * @return
     */
    @Override
    public LineChartVo
    countupdataClient(LocalDate beginCreate, LocalDate endCreate) {
        List<LocalDate> xAxis = new ArrayList<>();
        while (!beginCreate.equals(endCreate)) {
            beginCreate = beginCreate.plusDays(1);
            xAxis.add(beginCreate);
        }
        //每天新增
        List<Object> data = new ArrayList<>();
        //总数
        List<Object> list = new ArrayList<>();
        List<String> strings = new ArrayList<>();
        for (LocalDate localDate : xAxis) {
            LocalDateTime endtimeTime = LocalDateTime.of(localDate, LocalTime.MAX);
            LocalDateTime bingtimeTime = LocalDateTime.of(localDate, LocalTime.MIN);
            LambdaQueryWrapper<Contract> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.gt(null != bingtimeTime, Contract::getCreateTime, bingtimeTime)
                    .lt(null != endtimeTime, Contract::getCreateTime, endtimeTime)
                    .eq(Contract::getStatus, Constants.STATUS_PERFORM);
            Long count = this.count(queryWrapper);
            //每天新增数量
            data.add(count);
            LambdaQueryWrapper<Contract> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.lt(null != bingtimeTime, Contract::getCreateTime, endtimeTime);
            Long count1 = this.count(queryWrapper1);
            list.add(count1);
            String string = localDate.toString();
            strings.add(string);
        }
        LineSeriesVo lineSeriesVo = new LineSeriesVo();
        lineSeriesVo.setData(data);
        lineSeriesVo.setName("每天新增");
        LineSeriesVo lineSeriesVo1 = new LineSeriesVo();
        lineSeriesVo1.setName("总用户数");
        lineSeriesVo1.setData(list);
        List<LineSeriesVo> series = new ArrayList<>();
        series.add(lineSeriesVo);
        series.add(lineSeriesVo1);
        LineChartVo lineChartVo = new LineChartVo();
        lineChartVo.setxAxis(strings);
        lineChartVo.setSeries(series);
        return lineChartVo;
    }

    /**
     * 获取日期列表
     *
     * @param begin
     * @param end
     * @return
     */
    private static List<LocalDate> getLocalDates(LocalDate begin, LocalDate end) {
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(begin);
        //定义一个循环 从开始时间开始每次加一天,当到最后一天 结束循环
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            //将数据存入集合
            dateList.add(begin);
        }
        return dateList;
    }

    /**
     * 销售统计归属人报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> ownerShipStatisticsList(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("create_by", "count(id) as num", "round(sum(contract_order), 2) as total_amount")
                .groupBy("create_by")
                .orderByDesc("total_amount");
        if (beginCreateTime != null) {
            queryWrapper.ge("create_time", bingtimeTime);
        }
        if (endCreateTime != null) {
            queryWrapper.le("create_time", endtimeTime);
        }
        List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
        return maps;
    }

    @Resource
    private TbActivityMapper tbActivityMapper;
    @Resource
    public SysDictDataMapper sysDictDataMapper;

    /**
     * 销售统计归属渠道明细列表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> channelStatisticsList(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("channel", "count(id) as num", "round(sum(contract_order), 2) as total_amount")
                .groupBy("channel")
                .orderByDesc("total_amount");
        if (beginCreateTime != null) {
            queryWrapper.ge("create_time", bingtimeTime);
        }
        if (endCreateTime != null) {
            queryWrapper.le("create_time", endtimeTime);
        }
        List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
        for (Map<String, Object> map : maps) {
            String dictValue = (String) map.get("channel");
            LambdaQueryWrapper<DictData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DictData::getDictType, "clues_item")
                    .eq(null != dictValue, DictData::getDictValue, dictValue);
            DictData dictData = sysDictDataMapper.selectOne(lambdaQueryWrapper);
            map.put("channel", dictData.getDictLabel());
        }
        return maps;

    }

    @Resource
    private SysDeptMapper sysDeptMapper;

    /**
     * 销售统计归属部门明细列表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> deptStatisticsList(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("dept_id", "count(id) as num", "round(sum(contract_order), 2) as total_amount")
                .groupBy("dept_id")
                .orderByDesc("total_amount");
        if (beginCreateTime != null) {
            queryWrapper.ge("create_time", bingtimeTime);
        }
        if (endCreateTime != null) {
            queryWrapper.le("create_time", endtimeTime);
        }
        List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
        LambdaQueryWrapper<Dept> deptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        for (Map<String, Object> map : maps) {
            Long deptId = (Long) map.get("dept_id");
            if (deptId.equals(null)) {
                throw new CustomException("用户没有部门,数据错误");

            }
            Dept dept = sysDeptMapper.selectById(deptId);
            map.put("deptName", dept.getDeptName());
        }

        return maps;
    }

    /**
     * 客户统计学科分布统计报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> subjectStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        if (beginCreateTime != null) {
            queryWrapper.ge("create_time", bingtimeTime);
        }
        if (endCreateTime != null) {
            queryWrapper.le("create_time", endtimeTime);
        }

        queryWrapper.select("count(1) as num, subject")
                .groupBy("subject");
        List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
        for (Map<String, Object> map : maps) {
            String subject = (String) map.get("subject");
            LambdaQueryWrapper<DictData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DictData::getDictType, "course_subject")
                    .eq(null != subject, DictData::getDictValue, subject);
            DictData dictData = sysDictDataMapper.selectOne(lambdaQueryWrapper);
            map.put("subject", dictData.getDictLabel());
        }

        return maps;
    }

    /**
     * 销售统计报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public LineChartVo salesStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        List<Object> list = new ArrayList<>();
        List<LineSeriesVo> lists = new ArrayList<>();
        LineChartVo lineChartVo = new LineChartVo();
        List<LocalDate> localDates = getLocalDates(beginCreateTime, endCreateTime);
        List<String> strings = new ArrayList<>();
        for (LocalDate localDate : localDates) {
            LocalDateTime endTime = LocalDateTime.of(localDate, LocalTime.MAX);
            LocalDateTime beginTime = LocalDateTime.of(localDate, LocalTime.MIN);
            QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("round(sum(contract_order), 2) as contract_order")
                    .eq("status", Constants.STATUS_PERFORM);
            if (beginTime != null) {
                queryWrapper.ge("create_time", beginTime);
            }
            if (endCreateTime != null) {
                queryWrapper.le("create_time", endTime);
            }
            List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
            String string = localDate.toString();
            strings.add(string);
            for (Map<String, Object> map : maps) {

                if (Objects.isNull(map)) {
                    Double sumContractOrder = 0.0;
                    list.add(sumContractOrder);
                } else {
                    //每天的销售额
                    Double sumContractOrder = (Double) map.get("contract_order");
                    list.add(sumContractOrder);
                }
            }
        }
        LineSeriesVo lineSeriesVo = new LineSeriesVo();
        lineSeriesVo.setName("每天销售统计");
        lineSeriesVo.setData(list);
        lists.add(lineSeriesVo);
        lineChartVo.setSeries(lists);
        lineChartVo.setxAxis(strings);
        return lineChartVo;
    }

    @Resource
    private TbClueMapper tbClueMapper;

    /**
     * 线索统计明细列表
     *
     * @param tbCluePageDTO
     * @return
     */
    @Override
    public List<ClueReportVo> cluesStatisticsList(TbCluePageDTO tbCluePageDTO) {
        List<ClueReportVo> list = tbClueMapper.cluesStatisticsList(tbCluePageDTO);
        return list;
    }

    /**
     * 线索统计新增线索数量报表
     *
     * @param beginCreate
     * @param endCreate
     * @return
     */
    @Override
    public LineChartVo cluesStatistics(LocalDate beginCreate, LocalDate endCreate) {
        List<LocalDate> xAxis = new ArrayList<>();
        while (!beginCreate.equals(endCreate)) {
            beginCreate = beginCreate.plusDays(1);
            xAxis.add(beginCreate);
        }
        //每天新增
        List<Object> data = new ArrayList<>();
        //总数
        List<Object> list = new ArrayList<>();
        List<String> strings = new ArrayList<>();
        for (LocalDate localDate : xAxis) {
            LocalDateTime endtimeTime = LocalDateTime.of(localDate, LocalTime.MAX);
            LocalDateTime bingtimeTime = LocalDateTime.of(localDate, LocalTime.MIN);
            QueryWrapper<Clue> queryWrapper = new QueryWrapper<>();
            queryWrapper.select("count(1) as num");
            if (bingtimeTime != null) {
                queryWrapper.ge("create_time", bingtimeTime);
            }
            if (endtimeTime != null) {
                queryWrapper.le("create_time", endtimeTime);
            }
            List<Map<String, Object>> maps = tbClueMapper.selectMaps(queryWrapper);
            for (Map<String, Object> map : maps) {
                Long count = (Long) map.get("num");
                data.add(count);
            }
            //每天新增数量
            QueryWrapper<Clue> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.select("count(1) as num");
            if (endtimeTime != null) {
                queryWrapper1.le("create_time", endtimeTime);
            }
            List<Map<String, Object>> maps1 = tbClueMapper.selectMaps(queryWrapper1);
            for (Map<String, Object> map1 : maps1) {
                Long count1 = (Long) map1.get("num");
                list.add(count1);
            }
            String string = localDate.toString();
            strings.add(string);
        }
        LineSeriesVo lineSeriesVo = new LineSeriesVo();
        lineSeriesVo.setData(data);
        lineSeriesVo.setName("每天新增");
        LineSeriesVo lineSeriesVo1 = new LineSeriesVo();
        lineSeriesVo1.setName("总用户数");
        lineSeriesVo1.setData(list);
        List<LineSeriesVo> series = new ArrayList<>();
        series.add(lineSeriesVo);
        series.add(lineSeriesVo1);
        LineChartVo lineChartVo = new LineChartVo();
        lineChartVo.setxAxis(strings);
        lineChartVo.setSeries(series);
        return lineChartVo;

    }

    @Resource
    private TbBusinessMapper tbBusinessMapper;

    /**
     * 客户统计学科分布统计报表
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public VulnerabilityMapVo getVulnerabilityMap(LocalDate beginCreateTime, LocalDate endCreateTime) {
        VulnerabilityMapVo vulnerabilityMapVo = new VulnerabilityMapVo();
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        //总线索
        QueryWrapper<Clue> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda()
                .ge(bingtimeTime != null, Clue::getCreateTime, bingtimeTime)
                .le(endtimeTime != null, Clue::getCreateTime, endtimeTime);
        Integer aLong1 = Math.toIntExact(tbClueMapper.selectCount(queryWrapper1));
        vulnerabilityMapVo.setCluesNums(aLong1);
        //有效线索
        QueryWrapper<Clue> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.in("status", Arrays.asList("1", "2"));
        if (bingtimeTime != null) {
            queryWrapper2.ge("create_time", bingtimeTime);
        }
        if (endtimeTime != null) {
            queryWrapper2.le("create_time", endtimeTime);
        }
        Integer aLong = Math.toIntExact(tbClueMapper.selectCount(queryWrapper2));
        vulnerabilityMapVo.setEffectiveCluesNums(aLong);
        //商机数
        QueryWrapper<Business> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.lambda()
                .isNotNull(Business::getClueId)
                .in(Business::getStatus, 1, 2, 4, 7)
                .ge(bingtimeTime != null, Business::getCreateTime, bingtimeTime)
                .le(endtimeTime != null, Business::getCreateTime, endtimeTime);
        Integer aLong2 = Math.toIntExact(tbBusinessMapper.selectCount(queryWrapper3));
        vulnerabilityMapVo.setBusinessNums(aLong2);

        //合同
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .ge(bingtimeTime != null, Contract::getCreateTime, bingtimeTime)
                .le(endtimeTime != null, Contract::getCreateTime, endtimeTime);
        Integer aLong3 = Math.toIntExact(sysReportMapper.selectCount(queryWrapper));
        vulnerabilityMapVo.setContractNums(aLong3);


        return vulnerabilityMapVo;
    }

    /**
     * 渠道统计活动明细列表
     *
     * @param tbActivityDTO
     * @return
     */
    @Override
    @Transactional
    public List<ActivityStatisticsVo> activityStatisticsList(TbActivityDTO tbActivityDTO) {
        LambdaQueryWrapper<Activity> queryWrapper = new LambdaQueryWrapper<>();
        List<ActivityStatisticsVo> list = new ArrayList<>();
        queryWrapper.like(null != tbActivityDTO.getCode(), Activity::getCode, tbActivityDTO.getCode())
                .like(null != tbActivityDTO.getName(), Activity::getName, tbActivityDTO.getName())
                .eq(Activity::getStatus, "2");
        List<Activity> activities = tbActivityMapper.selectList(queryWrapper);
        for (Activity activity : activities) {
            ActivityStatisticsVo activityStatisticsVo = new ActivityStatisticsVo();
            BeanUtils.copyProperties(activity, activityStatisticsVo);
            Date from = Date.from(activity.getCreateTime().atZone(ZoneId.systemDefault()).toInstant());
            activityStatisticsVo.setCreateTime(from);

            LambdaQueryWrapper<DictData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DictData::getDictType, "clues_item")
                    .eq(null != activity.getChannel(), DictData::getDictValue, activity.getChannel());
            DictData dictData = sysDictDataMapper.selectOne(lambdaQueryWrapper);
            activityStatisticsVo.setChannel(dictData.getDictLabel());

            LambdaQueryWrapper<Clue> clueLambdaQueryWrapper = new LambdaQueryWrapper<>();
            clueLambdaQueryWrapper.eq(null != activity.getId(), Clue::getActivityId, activity.getId())
                    .eq(null != activity.getChannel(), Clue::getChannel, activity.getChannel());
            //线索总数
            Long aLong = tbClueMapper.selectCount(clueLambdaQueryWrapper);
            activityStatisticsVo.setCluesNum(Math.toIntExact(aLong));

            LambdaQueryWrapper<Clue> clueLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            clueLambdaQueryWrapper1.eq(null != activity.getId(), Clue::getActivityId, activity.getId())
                    .eq(null != activity.getChannel(), Clue::getChannel, activity.getChannel())
                    .eq(Clue::getStatus, "4");
            //伪线索数
            Long aLong1 = tbClueMapper.selectCount(clueLambdaQueryWrapper1);
            activityStatisticsVo.setFalseCluesNum(Math.toIntExact(aLong1));

            LambdaQueryWrapper<Business> businessLambdaQueryWrapper = new LambdaQueryWrapper<>();
            businessLambdaQueryWrapper.eq(null != activity.getId(), Business::getActivityId, activity.getId());
            //转化商机数
            Long aLong2 = tbBusinessMapper.selectCount(businessLambdaQueryWrapper);
            activityStatisticsVo.setBusinessNum(Math.toIntExact(aLong2));

            LambdaQueryWrapper<Contract> contractLambdaQueryWrapper = new LambdaQueryWrapper<>();
            contractLambdaQueryWrapper.eq(null != activity.getId(), Contract::getActivityId, activity.getId());
            //转换客户数
            Integer count = Math.toIntExact(this.count(contractLambdaQueryWrapper));
            activityStatisticsVo.setCustomersNum(count);

            QueryWrapper<Contract> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.select("round(sum(contract_order), 2) as contract_order", "round(sum(course_price), 2) as course_price")
                    .eq("status", Constants.STATUS_PERFORM)
                    .eq(null != activity.getId(), "activity_id", activity.getId())
                    .eq(null != activity.getChannel(), "channel", activity.getChannel());
            List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper2);
            for (Map<String, Object> map : maps) {
                if (!Objects.isNull(map)) {
                    //成交金额
                    Double contractOrder = (Double) map.get("contract_order");
                    Double create = (Double) map.get("course_price");
                    //活动成本
                    Double ccc = create - contractOrder;
                    activityStatisticsVo.setAmount(contractOrder);
                    activityStatisticsVo.setCost(create);
                } else {
                    Double contractOrder = 0.0;
                    Double create = 0.0;
                    //活动成本
                    Double ccc = create - contractOrder;
                    activityStatisticsVo.setAmount(contractOrder);
                    activityStatisticsVo.setCost(create);
                }

            }
            list.add(activityStatisticsVo);
        }
        return list;
    }

    /**
     * 渠道统计
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> chanelStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("channel", "count(id) as num")
                .groupBy("channel");

        if (beginCreateTime != null) {
            queryWrapper.ge("create_time", bingtimeTime);
        }
        if (endCreateTime != null) {
            queryWrapper.le("create_time", endtimeTime);
        }
        List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
        for (Map<String, Object> map : maps) {
            String dictValue = (String) map.get("channel");
            LambdaQueryWrapper<DictData> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(DictData::getDictType, "clues_item")
                    .eq(null != dictValue, DictData::getDictValue, dictValue);
            DictData dictData = sysDictDataMapper.selectOne(lambdaQueryWrapper);
            map.put("channel", dictData.getDictLabel());

        }
        return maps;
    }

    @Override
    public List<Map<String, Object>> activityStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime endtimeTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        LocalDateTime bingtimeTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        QueryWrapper<Contract> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("activity_id", "count(id) as num")
                .groupBy("activity_id");

        if (beginCreateTime != null) {
            queryWrapper.ge("create_time", bingtimeTime);
        }
        if (endCreateTime != null) {
            queryWrapper.le("create_time", endtimeTime);
        }
        List<Map<String, Object>> maps = sysReportMapper.selectMaps(queryWrapper);
        for (Map<String, Object> map : maps) {
            Long createTime = (Long) map.get("activity_id");
            Activity activity = tbActivityMapper.selectById(createTime);
            if (Objects.isNull(activity)){
                map.put("activity","其他");
            }else {
                map.put("activity",activity.getName());
            }
        }
        return maps;
    }
}